import pao = require('../public');
import server = require('./server');
import orm = require('typeorm');
import "reflect-metadata";

/**
 * 模块名称
 */
const moduleName = "pao.data";

/**
 * 默认数据库名称
 */
const defaultDatabaseName = "default";

/********    数据库      ********/

/**
 * 数据连接对象
 */
@pao.addon("数据连接对象", "用于保存数据连接的对象", moduleName)
export class dataConnectionInfo extends pao.baseObject {

    /**
     * 数据库连接配置
     * @remark 可以是连接的字符串，或者连接的配置对象
     */
    dbConnection?: orm.ConnectionOptions;

    /**
     * 当前TypeORM的连接对象
     */
    private _currentConnection?: orm.Connection = undefined;

    private databaseManager:orm.ConnectionManager;

    /**
     * 连接数据库
     */
    async connect?(): Promise<orm.Connection> {
        if(!this.databaseManager){
            this.databaseManager = orm.getConnectionManager();
        }
        if (this.dbConnection) {
            // 当前数据库连接的名称
            let databaseName = this.dbConnection.name ? this.dbConnection.name : defaultDatabaseName;
            if (this.databaseManager.has(databaseName)) {
                this._currentConnection = this.databaseManager.get(databaseName);
            } else {
                this._currentConnection = this.databaseManager.create(this.dbConnection);
            }            
        }
        // 关闭
        if (this._currentConnection.isConnected) { 
            await this._currentConnection.close();
        }
        // 返回连接的Promise对象
        return await this._currentConnection.connect();
    }
}

/********    数据服务      ********/
/**
 * 数据服务
 */
@pao.addon("数据服务", "通过数据库获取数据的服务", moduleName)
export class dataServiceFetcher extends pao.baseDataFetcher {
    /**
     * 数据连接信息
     */
    connectionInfo: dataConnectionInfo | any;

    /**
     * 命令列表
     */
    commandList: pao.dataCommandInfo[];

    /**
     * 获取命令信息
     * @param commandID 命令ID
     */
    getCommandByID?(commandID: string): pao.dataCommandInfo {
        if (this.commandList) {
            for (let cmd of this.commandList) {
                if (cmd.id == commandID) {
                    return cmd;
                }
            }
        }
        return undefined;
    }

    /**
     * 获取表格式
     */
    getSchema?(): pao.dataColumn[] {

        return undefined;
    }

    /**
     * 获取参数数组
     * @param paramValues 参数
     */
    getParameters(paramValues:{}):any[]{
        let param: any[] = [];
        for (let key in paramValues) {
            param.push(paramValues[key]);
        }
        return param;
    }

    /**
     * 源数据转Table对象
     * @param origin 
     */
    toTable(origin: any): pao.dataTable {
        let table: pao.dataTable = new pao.dataTable();
        table.name = "table";
        table.rows = [];
        // 列
        if (origin.length > 0) {
            for (let key in origin[0]) {
                let column = new pao.dataColumn();
                column.name = key;
                column.caption = key;
                table.addColumn(column);
            }
        }
        // 行
        for (let index in origin) {
            table.rows[index] = {};
            for (let key in origin[index]) {
                table.rows[index][key] = origin[index][key];
            }
        }
        return table;
    }

    /**
     * 查询
     * @param command 查询命令，可以是命令ID也可以是命令字符串
     * @param startIndex 起始索引
     * @param maxCount 最大行数
     * @param paramValues 参数值
     */
    query(command: string, paramValues: {}, startIndex: number = 0, maxCount: number = 500): any {
        // 数据库连接对象
        let connectionInfo: dataConnectionInfo = undefined;
        try {
            // 获取命令,ID则获取
            let cmd = this.getCommandByID(command);
            if (!cmd) {
                throw new Error(`找不到[${command}]的命令`);
            }
            // 待执行的SQL语句
            let executeSql = cmd.getCommandText(paramValues);
            let param = this.getParameters(paramValues);
            connectionInfo = pao.getObject<dataConnectionInfo>(this.connectionInfo);
            // 数据库不存在,或者数据库连接错误
            if(!connectionInfo){
                throw new  Error(`数据库不存在,或者数据库连接错误`);                                                                                 
            }
            return connectionInfo.connect()
                .then(connection => {
                    return connection.query(executeSql, param);
                })
                .then(result => {
                    // 获取分页
                    let page = result.slice(0).splice(startIndex,maxCount);
                    return this.toTable(page);
                })
                .catch(error => {
                    throw new Error(`执行语句[${executeSql}]，发生异常:${error.message}`);
                });
        } catch (error) {
            throw error;
        }
    }
}
